package com.itheima.service.mongo.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.itheima.domain.db.UserInfo;
import com.itheima.domain.mongo.Option;
import com.itheima.domain.mongo.SoulQuestion;
import com.itheima.domain.mongo.TestResult;
import com.itheima.domain.mongo.TestSoul;
import com.itheima.service.db.UserInfoService;
import com.itheima.service.db.UserService;
import com.itheima.service.mongo.TestSoulService;
import com.itheima.vo.OptionVo;
import com.itheima.vo.SoulQuestionVo;
import com.itheima.vo.TestRusultVo;
import com.itheima.vo.TestSoulVo;
import org.apache.dubbo.config.annotation.DubboService;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@DubboService
public class TestSoulServiceImpl implements TestSoulService {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public List<TestSoulVo> findTestSoul(Long userId) {
        List<TestSoul> testSouls = mongoTemplate.find(new Query(Criteria.where("userId").is(userId)), TestSoul.class);

        if (CollUtil.isEmpty(testSouls)) {
            saveTestSoul(userId);
        }


        List<TestSoulVo> testSoulVos = testSouls.stream().map(testSoul -> {
            TestSoulVo testSoulVo = new TestSoulVo();
            BeanUtil.copyProperties(testSoul, testSoulVo);
            testSoulVo.setId(testSoul.getId().toString());

            List<String> questionIds = testSoul.getQuestionIds();

            List<SoulQuestionVo> soulQuestionVos = questionIds.stream().map(questionId -> {
                SoulQuestionVo soulQuestionVo = new SoulQuestionVo();
                SoulQuestion soulQuestion = mongoTemplate.findOne(new Query(Criteria.where("_id").is(new ObjectId(questionId))), SoulQuestion.class);
                BeanUtil.copyProperties(soulQuestion, soulQuestionVo);
                soulQuestionVo.setId(questionId);

                List<String> optionIds = soulQuestion.getOptionIds();

                List<OptionVo> optionVos = optionIds.stream().map(optionId -> {
                    OptionVo optionVo = new OptionVo();
                    Option option = mongoTemplate.findOne(new Query(Criteria.where("_id").is(new ObjectId(optionId))), Option.class);
                    BeanUtil.copyProperties(option, optionVo);
                    optionVo.setId(optionId);

                    return optionVo;
                }).collect(Collectors.toList());

                soulQuestionVo.setOptions(optionVos);

                return soulQuestionVo;
            }).collect(Collectors.toList());

            testSoulVo.setQuestions(soulQuestionVos);

            return testSoulVo;
        }).collect(Collectors.toList());

        return testSoulVos;
    }

    @Override
    public int getScore(String optionId) {
        Option option = mongoTemplate.findOne(new Query(Criteria.where("_id").is(new ObjectId(optionId))), Option.class);

        Integer questionNum = option.getQuestionNum();
        String optionStr = option.getOptionStr();

        switch (questionNum) {
            case 1:
                switch (optionStr) {
                    case "A":
                        return 2;
                    case "B":
                        return 4;
                    case "C":
                        return 6;
                }
                break;
            case 2:
                switch (optionStr) {
                    case "A":
                        return 6;
                    case "B":
                        return 4;
                    case "C":
                        return 7;
                    case "D":
                        return 2;
                    case "E":
                        return 1;
                }
                break;
            case 3:
                switch (optionStr) {
                    case "A":
                        return 4;
                    case "B":
                        return 2;
                    case "C":
                        return 5;
                    case "D":
                        return 7;
                    case "E":
                        return 6;
                }
                break;
            case 4:
                switch (optionStr) {
                    case "A":
                        return 4;
                    case "B":
                        return 6;
                    case "C":
                        return 2;
                    case "D":
                        return 1;
                }
                break;
            case 5:
                switch (optionStr) {
                    case "A":
                        return 6;
                    case "B":
                        return 4;
                    case "C":
                        return 3;
                    case "D":
                        return 5;
                }
                break;
            case 6:
                switch (optionStr) {
                    case "A":
                        return 6;
                    case "B":
                        return 4;
                    case "C":
                        return 2;
                }
                break;
            case 7:
                switch (optionStr) {
                    case "A":
                        return 6;
                    case "B":
                        return 2;
                    case "C":
                        return 4;
                }
                break;
            case 8:
                switch (optionStr) {
                    case "A":
                        return 6;
                    case "B":
                        return 7;
                    case "C":
                        return 5;
                    case "D":
                        return 4;
                    case "E":
                        return 3;
                    case "F":
                        return 2;
                    case "G":
                        return 1;
                }
                break;
            case 9:
                switch (optionStr) {
                    case "A":
                        return 7;
                    case "B":
                        return 6;
                    case "C":
                        return 4;
                    case "D":
                        return 2;
                    case "E":
                        return 1;
                }
                break;
            case 10:
                switch (optionStr) {
                    case "A":
                        return 4;
                    case "B":
                        return 2;
                    case "C":
                        return 3;
                    case "D":
                        return 5;
                    case "E":
                        return 6;
                    case "F":
                        return 1;
                }
                break;
            default:
                return 0;
        }
        return 0;
    }

    @Override
    public String saveTestResult(TestResult testRusult) {
        mongoTemplate.save(testRusult);

        return testRusult.getId().toString();
    }

    @Override
    public TestResult findResultById(String id) {
        TestResult testRusult = mongoTemplate.findOne(new Query(Criteria.where("_id").is(new ObjectId(id))), TestResult.class);
        return testRusult;
    }

    @Override
    public List<TestResult> findResultByType(Integer type) {
        List<TestResult> list = mongoTemplate.find(new Query(Criteria.where("type").is(type)), TestResult.class);
        return list;
    }

    @Override
    public void saveTestSoul(TestSoulVo testSoulVo,Long userId) {
        TestSoul testSoul = new TestSoul();
        testSoul.setId(new ObjectId(testSoulVo.getId()));
        testSoul.setName(testSoulVo.getName());
        testSoul.setCover(testSoulVo.getCover());
        testSoul.setLevel(testSoulVo.getLevel());
        testSoul.setStar(testSoulVo.getStar());
        List<SoulQuestionVo> questions = testSoulVo.getQuestions();
        List<String> list = new ArrayList<>();
        for (SoulQuestionVo soulQuestionVo : questions) {
            list.add(soulQuestionVo.getId());
        }
        testSoul.setQuestionIds(list);
        testSoul.setIsLock(testSoulVo.getIsLock());
        testSoul.setReportId(testSoulVo.getReportId());
        testSoul.setUserId(userId);
        mongoTemplate.save(testSoul);
    }

    @Override
    public Integer getQuestionNum(String optionId) {
        Option option = mongoTemplate.findOne(new Query(Criteria.where("_id").is(new ObjectId(optionId))), Option.class);
        return option.getQuestionNum();
    }

    private void saveTestSoul(Long userId) {
        TestSoul testSoul1 = new TestSoul();
        TestSoul testSoul2 = new TestSoul();
        TestSoul testSoul3 = new TestSoul();

        testSoul1.setName("初级灵魂题");
        testSoul2.setName("中级灵魂题");
        testSoul3.setName("高级灵魂题");

        testSoul1.setCover("https://tanhua-dev.oss-cn-zhangjiakou.aliyuncs.com/images/test_soul/qn_cover_01.png");
        testSoul2.setCover("https://tanhua-dev.oss-cn-zhangjiakou.aliyuncs.com/images/test_soul/qn_cover_02.png");
        testSoul3.setCover("https://tanhua-dev.oss-cn-zhangjiakou.aliyuncs.com/images/test_soul/qn_cover_03.png");

        testSoul1.setLevel("初级");
        testSoul2.setLevel("中级");
        testSoul3.setLevel("高级");

        testSoul1.setStar(3);
        testSoul2.setStar(4);
        testSoul3.setStar(5);

        List<String> questions1 = new ArrayList<>();
        List<String> questions2 = new ArrayList<>();
        List<String> questions3 = new ArrayList<>();

        questions1.add(mongoTemplate.findOne(new Query(Criteria.where("_id").is(new ObjectId("636e16e997b5856012a3db3a"))), SoulQuestion.class).getId().toString());
        questions1.add(mongoTemplate.findOne(new Query(Criteria.where("_id").is(new ObjectId("636e179681d52f6b5c72be1f"))), SoulQuestion.class).getId().toString());
        questions1.add(mongoTemplate.findOne(new Query(Criteria.where("_id").is(new ObjectId("636e17facafca773e38c44b3"))), SoulQuestion.class).getId().toString());

        questions2.add(mongoTemplate.findOne(new Query(Criteria.where("_id").is(new ObjectId("636e185cd3b0933438af10cc"))), SoulQuestion.class).getId().toString());
        questions2.add(mongoTemplate.findOne(new Query(Criteria.where("_id").is(new ObjectId("636e18a09dd5714054358c57"))), SoulQuestion.class).getId().toString());
        questions2.add(mongoTemplate.findOne(new Query(Criteria.where("_id").is(new ObjectId("636e18ea7525ea2ed37c5b60"))), SoulQuestion.class).getId().toString());

        questions3.add(mongoTemplate.findOne(new Query(Criteria.where("_id").is(new ObjectId("636e1929cb384f1ce8b906df"))), SoulQuestion.class).getId().toString());
        questions3.add(mongoTemplate.findOne(new Query(Criteria.where("_id").is(new ObjectId("636e1989d6a2cf7ddf752e0f"))), SoulQuestion.class).getId().toString());
        questions3.add(mongoTemplate.findOne(new Query(Criteria.where("_id").is(new ObjectId("636e19dcb1a51a2fd7d2c9e5"))), SoulQuestion.class).getId().toString());
        questions3.add(mongoTemplate.findOne(new Query(Criteria.where("_id").is(new ObjectId("636e1a247150e726e9e24389"))), SoulQuestion.class).getId().toString());

        testSoul1.setQuestionIds(questions1);
        testSoul2.setQuestionIds(questions2);
        testSoul3.setQuestionIds(questions3);

        testSoul1.setIsLock(0);
        testSoul2.setIsLock(1);
        testSoul3.setIsLock(1);

        testSoul1.setUserId(userId);
        testSoul2.setUserId(userId);
        testSoul3.setUserId(userId);

        mongoTemplate.save(testSoul1);
        mongoTemplate.save(testSoul2);
        mongoTemplate.save(testSoul3);
    }
}
